package emums

import (
	"embed"
	_ "embed"
	"fmt"
	"os"
	"text/template"
	"unicode"
)

type EnumConfig struct {
	// 枚举描述
	Description string
	// 文件名称
	FileName string
	// 值类型
	ValType string
	// 值的零值
	ValZero string
	// 枚举变量名
	EnumName    string
	EnumDefType string
	// 枚举所在的包名
	PackageName string
	// 代码文件输出的路径
	OutPutPath string
	// 枚举变量名称对应的lable
	NLMap map[string]string
	// 枚举变量名称对应的value
	NVMap map[string]string
}

//go:embed templ/*
var emumDefTmpl embed.FS

func CreateEnum(ec EnumConfig) {
	//Go 模板提供了 title 函数，可以将字符串中每个单词的首字母大写

	ec.EnumDefType = firstLetterToLower(ec.EnumName)
	CreateDirIfNotExists(ec.OutPutPath)

	f, err := os.OpenFile(ec.OutPutPath+"/"+ec.FileName, os.O_CREATE|os.O_RDWR|os.O_TRUNC, os.ModeAppend|os.ModePerm)
	if nil != err {
		fmt.Printf(" %s create file error: %v", ec.OutPutPath+"/"+ec.FileName, err)
		return
	}

	tmpl, err := template.ParseFS(emumDefTmpl, "templ/enum_def.go.tmpl")
	if err != nil {
		fmt.Printf("--ParseFS error: %v", err)
		return
	}

	err = tmpl.Execute(f, ec)
	if err != nil {
		fmt.Printf("--Execute error: %v", err)
		return
	}
}

func CreateDirIfNotExists(path string) {
	exist, err := FileExists(path)
	if nil != err {
		fmt.Errorf(" %s CreateDirIfNotExists error: %v", path, err)
	} else {
		if !exist {
			CreateDir(path)
		}
	}
}

// FileExists
// @author:
// @function: FileExists
// @description: 文件目录是否存在
// @param: path string
// @return: bool, error
func FileExists(path string) (bool, error) {
	_, err := os.Stat(path)
	if err == nil {
		return true, nil
	}
	if os.IsNotExist(err) {
		return false, nil
	}
	return false, err
}

// CreateDir
// @author:
// @function: CreateDir
// @description: 批量创建文件夹
// @param: dirs ...string
// @return: err error
func CreateDir(dirs ...string) (err error) {
	for _, v := range dirs {
		exist, err := FileExists(v)
		if err != nil {
			return err
		}
		if !exist {
			//Logger.Debug("create directory" + v)
			err = os.MkdirAll(v, os.ModePerm)
		}
	}
	return err
}

func firstLetterToLower(s string) string {
	if s == "" {
		return s
	}
	r := []rune(s)               // 将字符串转换为rune切片，以便正确处理Unicode字符
	r[0] = unicode.ToLower(r[0]) // 将首字母转换为小写
	return string(r)             // 将rune切片转回字符串
}
